package com.dragon.mmochat.util;

import java.awt.Color;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Type;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.RandomAccess;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import com.dragon.mmochat.MmochatConstant;
import com.dragon.mmochat.MmochatMain;
import com.dragon.mmochat.message.Mmochat_SendSystenMsgToOtherServer;
import com.dragon.mmochat.model.enumType.MmochatHotType;
import com.dragon.mmochat.model.enumType.MmochatServerType;
import com.dragon.mmochat.model.role.MmochatPlayer;
import com.dragon.mmochat.service.MmochatHandle_SendChat;
import com.dragon.mmochat.service.MmochatHandle_SendMotion;
import com.dragon.mmochat.service.MmochatMainService;
import com.google.gson.Gson;
import com.skymobi.exception.NoConnectionException;
import com.skymobi.handler.SkymobiHandler;
import com.skymobi.message.SkymobiModuleMessage;
import com.skymobi.message.SkymobiProtocolMessage;
import com.skymobi.message.SkymobiProtocolMessage.UserConnInfo;
import com.skymobi.message.widget.CloseWinTLV;
import com.skymobi.message.widget.CreateMsgBoxTLV;
import com.skymobi.message.widget.CtrlTLVStructureRequest;
import com.skymobi.message.widget.TLVStructure;
import com.skymobi.util.Text;

public class MmochatUtil {
	private static final String colorHead = String.valueOf((char) 2);
	private static final String colorEnd = String.valueOf((char) 3);
	private static final String iconHead = String.valueOf((char) 4);
	private static final String bgIconHead = String.valueOf((char) 5);

	/**
	 * 富文本包装
	 * 
	 * @param info
	 * @param color
	 * @return
	 */
	public static String wrapColor(Object info, Color color) {
		int colorValue = ((color.getRed() >>> 3) << 11)
				+ ((color.getGreen() >>> 2) << 5) + (color.getBlue() >>> 3);
		String colorStr = String.valueOf((char) colorValue);
		return (colorHead + colorStr + info + colorEnd);
	}

	/**
	 * 富文本包装
	 * 
	 * @param bmpId
	 * @return
	 */
	public static String wrapIcon(int bmpId) {
		String bmp = String.valueOf((char) bmpId);
		return (iconHead + bmp);
	}

	public static String wrapBgIcon(int bmpId, int repeatNum) {
		String bmp = String.valueOf((char) bmpId);
		String repeat = String.valueOf((char) repeatNum);
		return (bgIconHead + repeat + bmp);
	}

	public static CtrlTLVStructureRequest msgbox(int hallState, String msg) {
		CreateMsgBoxTLV msgbox = new CreateMsgBoxTLV();
		msgbox.setContent(new Text(msg));
		msgbox.setLeftName("确定");
		return tlvResponse(hallState, msgbox);
	}
	
	public static CtrlTLVStructureRequest msgboxWithoutHallState(String msg) {
		CreateMsgBoxTLV msgbox = new CreateMsgBoxTLV();
		msgbox.setContent(new Text(msg));
		msgbox.setLeftName("确定");
		return tlvResponseWithoutHallState(msgbox);
	}

	public static CtrlTLVStructureRequest closeWindowAndShowMsgbox(
			int hallState, String msg, int winId) {
		CreateMsgBoxTLV msgbox = new CreateMsgBoxTLV();
		msgbox.setContent(new Text(msg));
		msgbox.setLeftName("确定");
		return tlvResponse(hallState, new CloseWinTLV(winId), msgbox);
	}

	public static void sendCommonMsgbox(MmochatPlayer p, String msg) {
		if (p == null || msg == null) {
			return;
		}
		CreateMsgBoxTLV msgbox = new CreateMsgBoxTLV();
		msgbox.setContent(new Text(msg));
		msgbox.setLeftName("确定");
		CtrlTLVStructureRequest pack = tlvResponseWithoutHallState(msgbox);
		sendCommonPack(p, pack);
	}

	public static void sendCommonMsgbox(UserConnInfo conn, String msg) {
		CreateMsgBoxTLV msgbox = new CreateMsgBoxTLV();
		msgbox.setContent(new Text(msg));
		msgbox.setLeftName("确定");
		CtrlTLVStructureRequest pack = tlvResponseWithoutHallState(msgbox);

		pack.setSrcId(MmochatMain.getModuleInstID());
		pack.setDstId(MmochatConstant.getClientModuleId());
		pack.setUserConnInfo(conn);
		SkymobiHandler handle = MmochatMainService.getCommonHandler();
		if (handle != null) {
			try {
				handle.pushSkymobiMessage(pack);
			} catch (NoConnectionException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public static CtrlTLVStructureRequest tlvResponse(int hallState,
			TLVStructure... tlvs) {
		CtrlTLVStructureRequest pack = new CtrlTLVStructureRequest(hallState,
				tlvs);
		pack.setSrcId(MmochatMain.getModuleInstID());
		pack.setDstId(MmochatConstant.getClientModuleId());
		pack.setMsgCode(MmochatConstant.MSGCODE_MMOCHAT_TLV_HALLSTATE);
		return pack;
	}

	public static CtrlTLVStructureRequest tlvResponseWithoutHallState(
			TLVStructure... tlvs) {
		CtrlTLVStructureRequest pack = new CtrlTLVStructureRequest(0, tlvs);
		pack.setSrcId(MmochatMain.getModuleInstID());
		pack.setDstId(MmochatConstant.getClientModuleId());
		pack.setMsgCode(MmochatConstant.MSGCODE_MMOCHAT_TLV);
		return pack;
	}

	public static void sendCommonPack(MmochatPlayer me,
			SkymobiProtocolMessage pack) {
		sendCommonPack(MmochatMainService.getCommonHandler(), me, pack);
	}

	public static void sendCommonPack(SkymobiHandler handle, MmochatPlayer me,
			SkymobiProtocolMessage pack) {
		if (me == null || pack == null || me.getUserConnInfo() == null) {
			return;
		}
		pack.setSrcId(MmochatMain.getModuleInstID());
		pack.setDstId(MmochatConstant.getClientModuleId());
		pack.setUserConnInfo(me.getUserConnInfo());
		if (handle != null) {
			try {
				handle.pushSkymobiMessage(pack);
			} catch (NoConnectionException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public static void sendMultiServerPack(SkymobiModuleMessage pack) {
		try {
			if (pack == null) {
				return;
			}
			if (MmochatMainService.getCommonHandler() != null) {
				MmochatMainService.getCommonHandler()
						.asyncPushSkymobiModuleMessage(pack, null);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// 按概率计算成功率
	public static boolean isInPercent(int percent) {
		int randValue = (int) (Math.random() * 100);
		if (randValue < percent) {
			return true;
		}
		return false;
	}

	public static boolean isInPercent(double percent) {
		double randValue = (double) (Math.random() * 100);
		if (randValue < percent) {
			return true;
		}
		return false;
	}

	// 获取一定范围内的随机数[0,maxValue-1]
	public static int getRandomValue(int maxValue) {
		return (int) (Math.random() * maxValue);
	}

	// 获取一定范围内的随机数[minValue,maxValue]
	public static int getRandomValue(int minValue, int maxValue) {
		int min = Math.min(minValue, maxValue);
		int max = Math.max(minValue, maxValue);
		return (int) (min + Math.random() * (max + 1 - min));
	}

	// 获取一定范围内的随机数[minValue,maxValue]
	public static double getRandomValue(double minValue, double maxValue) {
		double min = Math.min(minValue, maxValue);
		double max = Math.max(minValue, maxValue);
		return (double) (min + Math.random() * (max + 1 - min));
	}

	// 按波动幅度计算数值
	public static int getWaveValue(int value, int wavePercent) {
		if (wavePercent <= 0) {
			return value;
		}
		int waveValue = value * wavePercent / 100;
		waveValue = Math.max(1, waveValue);
		int randValue = (int) (Math.random() * (2 * waveValue));
		value = value - waveValue + randValue;
		return value;
	}

	// 获取不同钱数对应的颜色
	public static String getColorMoney(int money) {
		return getColorMoney((long) money);
	}

	public static String getColorMoney(long money) {
		if (money < 100000) {
			return wrapColor(money + "", Color.white);
		} else if (money < 1000000) {
			return wrapColor(money + "", Color.green);
		} else if (money < 10000000) {
			return wrapColor(money + "", Color.magenta);
		} else if (money < 100000000) {
			return wrapColor(money + "", Color.yellow);
		} else if (money < 1000000000) {
			return wrapColor(money + "", Color.red);
		} else {
			return wrapColor(money + "", Color.cyan);
		}
	}

	// 将道行转化成年月日
	public static String getDaoString(int dao) {
		String str = "";
		int year = dao / 365;
		int day = dao % 365;
		if (year > 0) {
			str += year + "年";
		}
		str += day + "天";
		return str;
	}

	// 将道行转化成年
	public static String getDaoSimpleString(int dao) {
		String str = "";
		int year = dao / 365;
		if (year >= 0) {
			str += year + "年";
		}
		return str;
	}

	// 将数组顺序随机打乱
	public static <T> ArrayList<T> messList(List<T> list) {
		Map<Integer, T> randList = new ConcurrentHashMap<Integer, T>();
		int base = getRandomValue(10000);
		for (T obj : list) {
			base += 1 + getRandomValue(100);
			randList.put(base, obj);
		}
		return new ArrayList<T>(randList.values());
	}

	// 写文件
	public static void writeToFile(String path, String msg) {
		try {
			File f = new File(path);
			FileWriter writer = new FileWriter(f, true);
			writer.write(msg + "\r\n");
			writer.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	// 获取组队奖励
	public static int getTeamAward(int totalAward, int playerNum) {
		double[] times = new double[] { 1, 2.2, 3.6, 5.2, 7 };
		return (int) (totalAward * times[playerNum - 1] / playerNum);
	}

	// 获取时间字符串,将ms数转成时间
	public static String getTimeString(long interval) {
		if (interval < MmochatConstant.MS_PER_MINUTE) {
			// 不足1分钟
			return "<1分";
		}
		int day = (int) (interval / MmochatConstant.MS_PER_DAY);
		interval -= day * MmochatConstant.MS_PER_DAY;
		int hour = (int) (interval / MmochatConstant.MS_PER_HOUR);
		interval -= hour * MmochatConstant.MS_PER_HOUR;
		int min = (int) (interval / MmochatConstant.MS_PER_MINUTE);
		String time = "";
		if (day > 0) {
			time += day + "天";
		}
		if (day > 0 || hour > 0) {
			time += hour + "小时";
		}
		time += min + "分";
		return time;
	}

	// 获取时间字符串,将ms数转成时间
	public static String getHourString(long interval) {
		if (interval < MmochatConstant.MS_PER_HOUR) {
			// 不足1小时
			return "<1小时";
		}

		int day = (int) (interval / MmochatConstant.MS_PER_DAY);
		interval -= day * MmochatConstant.MS_PER_DAY;
		int hour = (int) (interval / MmochatConstant.MS_PER_HOUR);

		String time = "";
		if (day > 0) {
			time += day + "天";
		}
		time += hour + "小时";

		return time;
	}

	// 获取时间字符串,将ms数转成时间
	public static String getMinString(long interval) {
		if (interval < MmochatConstant.MS_PER_HOUR) {
			// 不足1小时
			return "<1小时";
		}
		int hour = (int) (interval / MmochatConstant.MS_PER_HOUR);
		interval -= hour * MmochatConstant.MS_PER_HOUR;
		int min = (int) (interval / MmochatConstant.MS_PER_MINUTE);

		String time = "";
		if (hour > 0) {
			time += hour + "小时";
		}
		if (min > 0) {
			time += min + "分";
		}

		return time;
	}

	// 深度clone
	// 不会调用构造函数，需要特别注意这点
	// 目前凡是包含MmochatPet和MmochatCommonObjecct的对象或集合都不能使用这个接口
	// ConcurrentHashMap被clone后仍然是ConcurrentHashMap
	public static Object deepClone(Object srcObj) {
		Object cloneObj = null;
		try {
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			ObjectOutputStream oo = new ObjectOutputStream(out);
			oo.writeObject(srcObj);

			ByteArrayInputStream in = new ByteArrayInputStream(out
					.toByteArray());
			ObjectInputStream oi = new ObjectInputStream(in);
			cloneObj = oi.readObject();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return cloneObj;
	}

	/*
	 * // 深度clone public static <T> T deepClone(Object srcObj, Class<T> clazz) {
	 * if (srcObj == null) { return null; } Gson gson = new Gson(); String
	 * gsonString = gson.toJson(srcObj);
	 * 
	 * return gson.fromJson(gsonString, clazz); }
	 */
	// 深度clone
	// 会调用构造函数
	// 如果包含了MmochatPet或MmochatCommonObjet的对象或集合，则检查是否包含抽象对象和父类对象，
	// 不包含则使用此接口
	// ConcurrentHashMap被clone后是LinkedHashMap，需要自己转换!!!!!!!!!!!!!!!!
	public static Object deepClone(Object srcObj, Type typeOfT) {
		if (srcObj == null) {
			return null;
		}
		Gson gson = new Gson();
		String gsonString = gson.toJson(srcObj, typeOfT);

		return gson.fromJson(gsonString, typeOfT);
	}

	// 获取线空闲状态
	public static MmochatHotType getLineHotType(int curValue) {
		int hotValue = Math.min(MmochatConstant.maxRolePerServer
				/ MmochatConstant.maxMapLineNum,
				MmochatConstant.maxNormalRoleNumPerLine);
		hotValue = (int) (hotValue * 0.8);
		if (curValue >= hotValue) {
			return MmochatHotType.火爆;
		} else if (curValue >= hotValue / 4) {
			return MmochatHotType.一般;
		} else {
			return MmochatHotType.空闲;
		}
	}

	// 获取服空闲状态
	public static MmochatHotType getServerHotType(int curValue) {
		int max = MmochatConstant.maxRolePerServerForHotTag;
		if (curValue >= max * 0.5) {
			return MmochatHotType.火爆;
		} else if (curValue >= max * 0.1) {
			return MmochatHotType.一般;
		} else {
			return MmochatHotType.空闲;
		}
	}

	// 生成32位小写md5加密字符串
	public static String MD5(String s) {
		char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
				'a', 'b', 'c', 'd', 'e', 'f' };
		try {
			byte[] strTemp = s.getBytes();
			MessageDigest mdTemp = MessageDigest.getInstance("MD5");
			mdTemp.update(strTemp);
			byte[] md = mdTemp.digest();
			int j = md.length;
			char str[] = new char[j * 2];
			int k = 0;
			for (int i = 0; i < j; i++) {
				byte byte0 = md[i];
				str[k++] = hexDigits[byte0 >>> 4 & 0xf];
				str[k++] = hexDigits[byte0 & 0xf];
			}
			return new String(str);
		} catch (Exception e) {
			return null;
		}
	}

	// 字符串转数字
	public static Integer ParseString2Int(String str) {
		if (str == null) {
			return null;
		}
		try {
			int v = Integer.parseInt(str);
			return v;
		} catch (NumberFormatException e) {
			return null;
		}
	}

	// 消息发给所有区服
	public static void sendCommonPackToAllServer(SkymobiModuleMessage pack) {
		if (pack == null || MmochatMain.serverListInfo == null) {
			return;
		}
		for (Entry<Integer, Integer> entry : MmochatMain.serverListInfo
				.entrySet()) {
			Integer serverId = entry.getKey();
			if (serverId == null) {
				continue;
			}
			Integer instId = entry.getValue();
			if (instId != null && instId != MmochatMain.getModuleInstID()) {
				pack.setDstId(instId);
				MmochatUtil.sendMultiServerPack(pack);
			}
		}
	}

	private static int min(int one, int two, int three) {
		int min = one;
		if (two < min) {
			min = two;
		}
		if (three < min) {
			min = three;
		}
		return min;
	}

	private static int ld(String str1, String str2) {
		int d[][]; // 矩阵
		int n = str1.length();
		int m = str2.length();
		int i; // 遍历str1的
		int j; // 遍历str2的
		char ch1; // str1的
		char ch2; // str2的
		int temp; // 记录相同字符,在某个矩阵位置值的增量,不是0就是1
		if (n == 0) {
			return m;
		}
		if (m == 0) {
			return n;
		}
		d = new int[n + 1][m + 1];
		for (i = 0; i <= n; i++) { // 初始化第一列
			d[i][0] = i;
		}
		for (j = 0; j <= m; j++) { // 初始化第一行
			d[0][j] = j;
		}
		for (i = 1; i <= n; i++) { // 遍历str1
			ch1 = str1.charAt(i - 1);
			// 去匹配str2
			for (j = 1; j <= m; j++) {
				ch2 = str2.charAt(j - 1);
				if (ch1 == ch2) {
					temp = 0;
				} else {
					temp = 1;
				}
				// 左边+1,上边+1, 左上角+temp取最小
				d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1]
						+ temp);
			}
		}
		return d[n][m];
	}

	// 返回相似度0-100
	public static int getSimilarity(String str1, String str2) {
		int ld = ld(str1, str2);
		return (int) (100 - 100 * ld / Math.max(str1.length(), str2.length()));
	}

	public static String byte2hex(byte[] b) {
		StringBuilder sb = new StringBuilder(32);
		for (int i = 0; i < b.length; i++) {
			String s = Integer.toHexString(b[i] & 0xFF);
			sb.append(s.length() == 1 ? "0" + s : s);
		}
		return sb.toString().toUpperCase();
	}

	// 写监控数据
	public static void monitorLog(String info) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		String fileName = "monitor-" + sdf.format(new Date());
		writeToFile(fileName, info);
	}

	// 读取文件内容
	public static String readFile(String fileName) {
		File file = new File(fileName);
		return readFile(file);
	}

	// 读取文件内容
	public static String readFile(File file) {
		InputStream in = null;
		byte inputBuffer[] = null;

		try {
			in = new FileInputStream(file);
			inputBuffer = new byte[in.available()];
			in.read(inputBuffer);
			in.close();
		} catch (Exception e) {
			return "";
		}
		return (new String(inputBuffer));
	}
}
